/*
 * Copyright (c) 2012 Jonathan Tyers
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package uk.org.uplink.configproxy.validator;

import java.util.Collection;
import java.util.regex.Pattern;

import javax.inject.Inject;

import uk.org.uplink.configproxy.ConfigValue;
import uk.org.uplink.configproxy.MethodInfo;
import uk.org.uplink.configproxy.Patterns;
import uk.org.uplink.configproxy.exception.InvalidConfigurationValueException;

/**
 * Default {@link ConfigProxyValidator} that uses the <tt>pattern</tt> attribute on {@code @}{@link ConfigValue}s to construct a regular expression,
 * and validates values against that regular expression.
 * 
 * @author jonny
 */
public class PatternConfigProxyValidator implements ConfigProxyValidator {

	private final PatternSelector patternSelector;

	@Inject
	public PatternConfigProxyValidator(final PatternSelector patternSelector) {
		super();
		this.patternSelector = patternSelector;
	}

	@Override
	public void validate(final MethodInfo methodInfo, final Object result) {
		if (result == null) {
			return;
		}

		ConfigValue configValue = methodInfo.getConfigValue();
		String patternString = configValue.pattern();

		if (patternString == Patterns.AUTO) {
			patternString = patternSelector.selectPattern(methodInfo.getReturnType());
		}

		Pattern pattern = Pattern.compile(patternString);

		if (result instanceof Collection<?>) {
			for (Object item : (Collection<?>) result) {
				validate(item, configValue, pattern);
			}

		} else {
			validate(result, configValue, pattern);
		}
	}

	private void validate(final Object result, final ConfigValue configValue, final Pattern pattern) {
		if (!pattern.matcher(result.toString()).matches()) {
			throw new InvalidConfigurationValueException(String.format("key = %s, value = '%s'", configValue.key(), result));
		}
	}

}
